﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine.UI;
using System.Text;
using UnityEngine.Events;

public static partial class Extend
{
    #region Object

    public static int ToInt(this object obj)
    {
        return int.TryParse(obj.ToString(), out int n) ? n : 0;
    }

    public static long ToLong(this object obj)
    {
        return long.TryParse(obj.ToString(), out long n) ? n : 0;
    }

    public static float ToFloat(this object obj)
    {
        return float.TryParse(obj.ToString(), out float n) ? n : 0;
    }

    public static bool ToBool(this object obj)
    {
        return bool.TryParse(obj.ToString(), out bool n) ? n : false;
    }

    public static List<string> ToStringList(this object obj, char c)
    {
        List<string> list = new List<string>();
        string[] temp = obj.ToString().Split(c);
        if (temp.Length > 0)
        {
            for (int i = 0; i < temp.Length; i++)
            {
                list.Add(temp[i]);
            }
        }
        return list;
    }

    public static List<int> ToIntList(this object obj, char c)
    {
        List<int> list = new List<int>();
        string[] temp = obj.ToString().Split(c);
        if (temp.Length > 0)
        {
            for (int i = 0; i < temp.Length; i++)
            {
                list.Add(temp[i].ToInt());
            }
        }
        return list;
    }

    public static List<float> ToFloatList(this object obj, char c, int count = 0)
    {
        List<float> list = new List<float>();
        string[] temp = obj.ToString().Split(c);
        if (temp.Length > 1)
        {
            for (int i = 0; i < temp.Length; i++)
            {
                list.Add(temp[i].ToFloat());
            }
        }
        if (count != 0)
        {
            while (list.Count < count)
            {
                list.Add(0);
            }
        }
        return list;
    }

    public static Vector2 ToVector2(this object obj, char c)
    {
        var v2 = new Vector2(0, 0);
        string[] temp = obj.ToString().Split(c);
        if (temp.Length == 2)
        {
            v2.x = temp[0].ToFloat();
            v2.y = temp[1].ToFloat();
        }
        return v2;
    }


    public static Vector3 ToVector3(this object obj, char[] c)
    {
        var v3 = new Vector3(0, 0, 0);
        string[] temp = obj.ToString().Split(c);
        var index = 0;
        for (var i = 0; i < temp.Length; i++)
        {
            if (temp[i] != "")
            {
                if (index == 0)
                {
                    v3.x = temp[i].ToFloat();
                }
                else if (index == 1)
                {
                    v3.y = temp[i].ToFloat();
                }
                else if (index == 2)
                {
                    v3.z = temp[i].ToFloat();
                }
                index++;
            }
        }
        return v3;
    }

    public static Dictionary<int, int> ToDictionary_Int_Int(this object obj, char c0, char c1)
    {
        var dict = new Dictionary<int, int>();
        var strs0 = obj.ToString().Split(c0);
        for (int i = 0; i < strs0.Length; i++)
        {
            var strs1 = strs0[i].Split(c1);
            if (strs1.Length == 2)
            {
                if (int.TryParse(strs1[0], out int key) && int.TryParse(strs1[1], out int value))
                {
                    dict.AddOnce(key, value);
                }
            }
        }
        return dict;
    }

    public static Dictionary<string, int> ToDictionary_String_Int(this object obj, char c0, char c1)
    {
        var dict = new Dictionary<string, int>();
        var strs0 = obj.ToString().Split(c0);
        for (int i = 0; i < strs0.Length; i++)
        {
            var strs1 = strs0[i].Split(c1);
            if (strs1.Length == 2)
            {
                if (int.TryParse(strs1[1], out int value))
                {
                    dict.AddOnce(strs1[0].ToString(), value);
                }
            }
        }
        return dict;
    }

    #endregion

    #region Letter

    public static string IntToLetter(this int mInt)
    {
        string result;
        switch (mInt)
        {
            case 1:
                result = "A";
                break;
            case 2:
                result = "B";
                break;
            case 3:
                result = "C";
                break;
            case 4:
                result = "D";
                break;
            case 5:
                result = "E";
                break;
            case 6:
                result = "F";
                break;
            case 7:
                result = "G";
                break;
            case 8:
                result = "H";
                break;
            case 9:
                result = "I";
                break;
            case 10:
                result = "J";
                break;
            case 11:
                result = "K";
                break;
            case 12:
                result = "L";
                break;
            case 13:
                result = "M";
                break;
            case 14:
                result = "N";
                break;
            case 15:
                result = "O";
                break;
            case 16:
                result = "P";
                break;
            case 17:
                result = "Q";
                break;
            case 18:
                result = "R";
                break;
            case 19:
                result = "S";
                break;
            case 20:
                result = "T";
                break;
            case 21:
                result = "U";
                break;
            case 22:
                result = "V";
                break;
            case 23:
                result = "W";
                break;
            case 24:
                result = "X";
                break;
            case 25:
                result = "Y";
                break;
            case 26:
                result = "Z";
                break;
            default:
                result = "A";
                break;
        }
        return result;
    }

    public static int LetterToInt(this string str)
    {
        int result;
        switch (str)
        {
            case "A":
                result = 1;
                break;
            case "B":
                result = 2;
                break;
            case "C":
                result = 3;
                break;
            case "D":
                result = 4;
                break;
            case "E":
                result = 5;
                break;
            case "F":
                result = 6;
                break;
            case "G":
                result = 7;
                break;
            case "H":
                result = 8;
                break;
            case "I":
                result = 9;
                break;
            case "J":
                result = 10;
                break;
            case "K":
                result = 11;
                break;
            case "L":
                result = 12;
                break;
            case "M":
                result = 13;
                break;
            case "N":
                result = 14;
                break;
            case "O":
                result = 15;
                break;
            case "P":
                result = 16;
                break;
            case "Q":
                result = 17;
                break;
            case "R":
                result = 18;
                break;
            case "S":
                result = 19;
                break;
            case "T":
                result = 20;
                break;
            case "U":
                result = 21;
                break;
            case "V":
                result = 22;
                break;
            case "W":
                result = 23;
                break;
            case "X":
                result = 24;
                break;
            case "Y":
                result = 25;
                break;
            case "Z":
                result = 26;
                break;
            default:
                result = 1;
                break;
        }
        return result;
    }

    #endregion

    #region String

    public static int ToInt(this string str)
    {
        int i;
        if (int.TryParse(str, out i))
            return i;
        else
            return 0;
    }

    public static float ToFloat(this string str)
    {
        float f;
        if (float.TryParse(str, out f))
            return f;
        else
            return 0;
    }

    public static bool ToBool(this string str)
    {
        bool b;
        if (bool.TryParse(str, out b))
            return b;
        else
            return false;
    }

    public static uint ToUint(this string str)
    {
        uint i;
        if (uint.TryParse(str, out i))
            return i;
        else
            return 0;
    }

    public static void GetVersionInt(this string str,out int v1,out int v2)
    {
        var split = str.Split('.');
        v1 = split[0].ToInt();
        v2 = split[1].ToInt();
    }

    #endregion

    #region Animator

    public static void ClearEvent(this Animator animator)
    {
        AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
        for (int i = 0; i < clips.Length; i++)
        {
            AnimationClip clip = clips[i];
            clip.events = default(AnimationEvent[]);
        }
    }

    // public static bool AddFinishEvent(this Animator animator, string clipName, Callback callback)
    // {
    //     Debug.Log(animator.name + "-->" + clipName);
    //     AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
    //     for (int i = 0; i < clips.Length; i++)
    //     {
    //         AnimationClip clip = clips[i];
    //         if (clip.name == clipName)
    //         {
    //             var help = animator.GetComponent<AnimatorHelp>();
    //             if (help == null)
    //                 help = animator.gameObject.AddComponent<AnimatorHelp>();
    //             help.SetCallback(callback);

    //             AnimationEvent aEvent = new AnimationEvent();
    //             aEvent.time = clip.length;
    //             aEvent.functionName = "Finish";
    //             clip.AddEvent(aEvent);
    //             return true;
    //         }
    //     }
    //     return false;
    // }

    #endregion

    #region Dictionary

    public static TValue GetValue<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey key, TValue defaultValue = default(TValue))
    {
        if (map == null) return defaultValue;
        TValue value = default(TValue);
        if (map.TryGetValue(key, out value)) return value;
        return defaultValue;
    }

    public static void ForEach<TKey, TValue>(this Dictionary<TKey, TValue> map, Action<TKey, TValue> action)
    {
        using (Dictionary<TKey, TValue>.KeyCollection.Enumerator enumerator = map.Keys.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                action(enumerator.Current, map[enumerator.Current]);
            }
        }
    }

    public static void ForEach<TKey, TValue>(this Dictionary<TKey, TValue> map, Action<TValue> action)
    {
        using (Dictionary<TKey, TValue>.ValueCollection.Enumerator enumerator = map.Values.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                action(enumerator.Current);
            }
        }
    }

    public static bool AddOnce<TKey, TValue>(this Dictionary<TKey, TValue> map, TKey key, TValue value)
    {
        if (map.ContainsKey(key)) return false;
        map.Add(key, value);
        return true;
    }

    public static void AddToList<TKey, TValue>(this Dictionary<TKey, List<TValue>> map, TKey key, TValue value)
    {
        if (!map.ContainsKey(key)) map[key] = new List<TValue>();
        map[key].Add(value);
    }

    public static void AddOrPlus<TKey>(this Dictionary<TKey, int> map, TKey key, int value)
    {
        if (!map.ContainsKey(key)) map[key] = value;
        else map[key] += value;
    }

    public static List<TKey> ToKeyList<TKey, TValue>(this Dictionary<TKey, TValue> map)
    {
        TKey[] array = new TKey[map.Count];
        map.Keys.CopyTo(array, 0);
        return array.ToList();
    }

    public static List<TValue> ToList<TKey, TValue>(this Dictionary<TKey, TValue> map)
    {
        TValue[] array = new TValue[map.Count];
        map.Values.CopyTo(array, 0);
        return array.ToList();
    }

    public static void Remove<TKey, TValue>(this Dictionary<TKey, TValue> map, Func<TValue, bool> func)
    {
        TKey[] array = new TKey[map.Count];
        map.Keys.CopyTo(array, 0);
        for (int i = 0; i < array.Length; i++)
        {
            TKey key = array[i];
            TValue value = map[key];
            if (func(value)) map.Remove(key);
        }
    }

    #endregion

    #region Array

    public static List<T> ToList<T>(this T[] array)
    {
        List<T> list = new List<T>();
        for (int i = 0; i < array.Length; i++)
        {
            T item = array[i];
            list.Add(item);
        }
        return list;
    }

    public static void Add<T>(this List<T> list, List<T> add)
    {
        for (int i = 0; i < add.Count; i++)
        {
            var value = add[i];
            list.Add(value);
        }
    }

    public static void AddValue<T>(this List<T> list, T value)
    {
        if (!list.Contains(value))
            list.Add(value);
    }

    #endregion

    #region Transform

    public static T FindComponent<T>(this Transform tr, string name) where T : Component
    {
        T[] childs = tr.GetComponentsInChildren<T>();
        for (int i = 0; i < childs.Length; i++)
        {
            if (childs[i].name == name)
                return childs[i];
        }
        return default(T);
    }

    public static void SetActive(this Transform tr, bool active)
    {
        if (tr != null)
            tr.gameObject.SetActive(active);
    }

    #endregion

    #region Game

    /// <summary>
    /// 获取二维数组序号
    /// </summary>
    public static int GetIndex(this int[,] formation, int x, int y)
    {
        return formation.GetLength(0) * x + y + 1;
    }

    /// <summary>
    /// 根据序号转换成二维数组坐标
    /// </summary>
    public static void GetLocation(this int[,] formation, int index, out int x, out int y)
    {
        int row = formation.GetLength(0);
        x = (index - 1) % row;
        y = (index - 1) / row;
    }

    // public static DragonData Find(this List<DragonData> datas, long id)
    // {
    //     var data = datas.Find((d) => d.id == id);
    //     return data;
    // }

    public static void BackgroundEnable(this InputField field, bool enable)
    {
        field.GetComponent<Image>().enabled = enable;
    }

    #endregion
}